# file:: logic_entity.rb
# author::  Ralph M. Churchill
# version::
# date::
#
# This source code copyright (C) 2006 by Ralph M. Churchill
# All rights reserved.
#
# Released under the terms of the GNU General Public License
# See LICENSE file for additional information.

require 'models/entity'

module ActsLikeLogicEntity 
    require 'observer'
    include Observable

    properties :logic

    # Adds logic to the entity according to the new logic's stacking
    # rule.
    # [+new_logic+] an instance of a logic class to be added 
    def add_logic(new_logic)
        self.logic ||= []
        case new_logic.stacking_rule
        when :exclusive
            if self.logic.find{|l| l.class == new_logic.class}
                raise "Logic with type #{new_logic.class} already exists!"
            else
                self.logic << new_logic
            end
        when :stackable
            self.logic << new_logic
        when :replaceable
            del_logic(new_logic)
            self.logic << new_logic
        end
        # callback
        new_logic.do_added if new_logic.respond_to?(:do_added)
        # applied

        new_logic
    end
    # Deletes all logic that matches the object passed in (instance) or
    # the is an instance of the class passed in (class). The logic owners
    # must match if an owner is specified. The 'do_removed' callback will
    # be invoked for every logic instance being deleted.
    # [+logic+] An instance of a logic class or a logic class itself
    def del_logic(logic)
        raise "#{logic} does not belong to this entity (#{self})" if \
            logic.respond_to?(:owner) and logic.owner != self
        self.logic ||= []

        self.logic.map! do |mylogic|
            if mylogic.class == (logic.kind_of?(Class) ? logic : logic.class)
                mylogic.do_removed if mylogic.respond_to?(:do_removed)
                nil
            else
                mylogic
            end
        end.compact!
    end
    def do_action(action)
        puts "#{self} will do #{action}"
        self.logic ||= []
        self.logic.each do |logic|
            begin
                return false if not logic.do_action(action)
            rescue => e
                $stderr.puts("Logic #{logic} threw exception #{e}")
                $stderr.puts(e.backtrace.join("\n"))
            end
        end
        true
    end
end
